<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>变量和函数的提升-预解析</title>
</head>

<body>
  <script>
    /* 正常js执行顺序是从上到下，从左到右，遇到等号，先执行右边的，遇到return，先执行return 右边的，return下面的不执行。遇到函数的定义不执行，函数调用的时候才执行。但是在js中存在一种现象叫做预解析。 */

    // var a = 1;
    // alert(a)

    // alert(a)  // undefined ???
    // var a = 1;

    // 预解析的步骤:
    /*  var a;  // 全局的变量,前置声明
     alert(a)
     a = 1; */

    // fn1()  // 'fn1'
    // function fn1() {
    //   console.log('fn1');
    // }

    // 预解析的步骤:
    /* function fn1() {  // 前缀声明函数
      console.log('fn1');
    }
    fn1() */

    // 原始代码:
    // alert(a)
    // var a = 1;
    // fn1()  // 'fn1'
    // function fn1() {
    //   console.log('fn1');
    // }

    // 预解析后的代码:
    /*  var a;
     function fn1() {
       console.log('fn1--a', a);
     }
     alert(a)
     a = 1;
     fn1() */

    //   2.预解析的作用域范围：
    // 1. 函数内部
    // 2. script标签
    // 3. JS文件内


    function cat() {
      /*  console.log(name); // undefined
       var name = '波斯猫'
       console.log(name); // '波斯猫' */

      //  预解析后的代码:
      var name;
      console.log(name);
      name = '波斯猫'
      console.log(name);
      // 函数内声明的变量,会在函数代码开始之前,前置声明所有变量
    }
    // cat();

    function dog() {
      console.log(name);
      console.log(color);
      eat();
      var name = '海盗狗'
      var color = '黑白'
      function eat() {
        console.log('狗再喝水');
      }
    }

    // dog();

    //  js中要求: 先声明变量\函数,再使用.

    // fn3(); // Cannot access 'fn3' before initialization
    // 函数表达式,不能再赋值表达式之前,调用函数的.
    const fn3 = function () {
      console.log("fn3");
    }
    fn3()  // 只能在函数表达式之后调用函数.

    /*
    const fn3;
    fn3();
    fn3=function(){}
    */

  </script>

</body>

</html>